/**
 * 
 */
package org.ranch.model;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * This class represents an animal.
 * 
 */
@Entity
@Table(name = "animal")
@Inheritance(strategy = InheritanceType.JOINED)
public class Animal extends BaseData implements Comparable<Animal>, Serializable {

    /**
     * Default serial Version UID
     */
    private static final long serialVersionUID = 1L;
    /** Type of animal */
    private Concept type;
    /** Ear tag */
    private String earTag;
    /** Animal weight */
    private int weight;
    /** Name */
    private String name;
    /** Animal picture */
    private byte[] picture = new byte[1];
    /** Health status */
    private Concept healthStatus;
    /** D.O.B */
    private Date dateOfBirth;
    /** Animal color */
    private Concept colour;
    /** The kraal the animal belongs to */
    private Kraal kraal;
    /** Purchasing date */
    private Date purchaseDate;
    /** Animal description */
    private String description;
    /** Animal breed */
    private Concept breed;
    /** Birth weight */
    private int birthWeight;
    /** Selling price */
    private int sellingPrice;
    /** Buying price */
    private int buyingPrice;
    /** Aniaml status either infant sold etc */
    private Concept status;
    /** Children */
    private List<Animal> children;

    /**
     * Default constructor
     */
    public Animal() {
        super();
    }

    /**
     * @return the type
     */
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "type", nullable = false)
    public Concept getType() {
        return type;
    }

    /**
     * @param type
     *            the type to set
     */
    public void setType(Concept type) {
        this.type = type;
    }

    /**
     * @return the earTag
     */
    @Column(name = "ear_tag", nullable = false)
    public String getEarTag() {
        return earTag;
    }

    /**
     * @param earTag
     *            the earTag to set
     */
    public void setEarTag(String earTag) {
        this.earTag = earTag;
    }

    /**
     * @return the weight
     */
    @Column(name = "weight", nullable = false)
    public int getWeight() {
        return weight;
    }

    /**
     * @param weight
     *            the weight to set
     */
    public void setWeight(int weight) {
        this.weight = weight;
    }

    /**
     * @return the name
     */
    @Column(name = "name", nullable = false)
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the picture
     */
    @Lob
    @Column(name = "picture", nullable = true)
    public byte[] getPicture() {
        return picture;
    }

    /**
     * @param picture
     *            the picture to set
     */
    public void setPicture(byte[] picture) {
        this.picture = picture;
    }

    /**
     * @return the healthStatus
     */
    
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "health_status", nullable = false)
    public Concept getHealthStatus() {
        return healthStatus;
    }

    /**
     * @param healthStatus
     *            the healthStatus to set
     */
    public void setHealthStatus(Concept healthStatus) {
        this.healthStatus = healthStatus;
    }

    /**
     * @return the dateOfBirth
     */
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "date_of_birth", nullable = true)
    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    /**
     * @param dateOfBirth
     *            the dateOfBirth to set
     */
    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    /**
     * @return the colour
     */
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "colour", nullable = false)
    public Concept getColour() {
        return colour;
    }

    /**
     * @param colour
     *            the colour to set
     */
    public void setColour(Concept colour) {
        this.colour = colour;
    }

    /**
     * @return the kraal
     */
    @ManyToOne
    @JoinColumn(name = "kraal_id", nullable = true)
    public Kraal getKraal() {
        return kraal;
    }

    /**
     * @param kraal
     *            the kraal to set
     */
    public void setKraal(Kraal kraal) {
        this.kraal = kraal;
    }

    /**
     * @return the purchaseDate
     */
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "date_purchase", nullable = true)
    public Date getPurchaseDate() {
        return purchaseDate;
    }

    /**
     * @param purchaseDate
     *            the purchaseDate to set
     */
    public void setPurchaseDate(Date purchaseDate) {
        this.purchaseDate = purchaseDate;
    }

    /**
     * @return the description
     */
    @Column(name = "decription")
    public String getDescription() {
        return description;
    }

    /**
     * @param description
     *            the description to set
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * @return the breed
     */
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "breed", nullable = false)
    public Concept getBreed() {
        return breed;
    }

    /**
     * @param breed
     *            the breed to set
     */
    public void setBreed(Concept breed) {
        this.breed = breed;
    }

    /**
     * @return the birthWeight
     */
    @Column(name = "birth_weight", nullable = true)
    public int getBirthWeight() {
        return birthWeight;
    }

    /**
     * @param birthWeight
     *            the birthWeight to set
     */
    public void setBirthWeight(int birthWeight) {
        this.birthWeight = birthWeight;
    }

    /**
     * @return the sellingPrice
     */
    @Column(name = "selling_price", nullable = true)
    public int getSellingPrice() {
        return sellingPrice;
    }

    /**
     * @param sellingPrice
     *            the sellingPrice to set
     */
    public void setSellingPrice(int sellingPrice) {
        this.sellingPrice = sellingPrice;
    }

    /**
     * @return the buyingPrice
     */
    @Column(name = "buying_price", nullable = true)
    public int getBuyingPrice() {
        return buyingPrice;
    }

    /**
     * @param buyingPrice
     *            the buyingPrice to set
     */
    public void setBuyingPrice(int buyingPrice) {
        this.buyingPrice = buyingPrice;
    }

    /**
     * @return the childrens
     */
    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "animal_children", joinColumns = @JoinColumn(name = "animal_id"),
    inverseJoinColumns = @JoinColumn(name = "children_id"))
    public List<Animal> getChildren() {
        return children;
    }

    /**
     * @param childrens
     *            the childrens to set
     */
    public void setChildren(List<Animal> children) {
        this.children = children;
    }

    
    
    /**
     * @return the status
     */
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "status", nullable = false)
    public Concept getStatus() {
        return status;
    }

    /**
     * @param status the status to set
     */
    public void setStatus(Concept status) {
        this.status = status;
    }

    @Override
    public int compareTo(Animal o) {
	return this.getName().compareToIgnoreCase(o.getName());
    }

    /**
     * adds a given child (animal) to this parent animal(this)
     *
     * @param child
    public void addChild(Animal child) {
	if (child == null) {
	    return;
	}

	if (getChildren() == null) {
	    setChildren(new ArrayList<Animal>());
	}

	getChildren().add(child);
        //child.set
	child.setStaffMemberse(this);
    }

    /**
     * removes a given animal (child) from this animal
     *
     * @param animal
     
    public void removeChild(Animal animal) {
	if (animal == null || getChildren() == null) {
	    return;
	}

	getChildren().remove(animal);
    }*/

}
